#pragma once
#include <unistd.h>
#include <iostream>
#include <typeinfo>

// any容器:由于有些地方其接收的数据类型可能是多种,用单一的容器无法满足所有情况
// 使用模板,将数据导入模板中使之自动生成对应类型的函数
class Any
{
private:
    class parent
    {
    public:
        virtual ~parent() {}
        virtual const std::type_info &type() = 0; // 获取数据类型
        virtual parent *clone() = 0;        // 克隆该数据 -> 赋值、赋值构造
    };

    template <class T>
    class child : public parent
    {
    public:
        child(const T &val) : _val(val) {}
        const std::type_info &type() { return typeid(T); }
        parent *clone() { return new child(_val); }

    public:
        T _val;
    };

private:
    parent *_content;

public:
    Any() { _content = nullptr; }

    template <class T>
    Any(const T &val) : _content(new child<T>(val)) {}
    Any(const Any &other) : _content(other._content == nullptr ? nullptr : other._content->clone()) {}
    ~Any() { delete _content; }

    Any &swap(Any &other)
    {
        std::swap(_content, other._content);
        return *this;
    }

    // 赋值运算符的重载函数
    template <class T>
    Any &operator=(const T &val)
    {
        // 为val构造一个临时的通用容器，然后与当前容器自身进行指针交换，临时对象释放的时候，原先保存的数据也就被释放
        Any(val).swap(*this);
        return *this;
    }
    Any &operator=(const Any &other)
    {
        Any(other).swap(*this);
        return *this;
    }
    
    template <class T>
    T *get()
    {
        assert(typeid(T) == _content->type()); // 防止接收类型与any容器内数据类型不同
        return &((child<T> *)_content)->_val;
    }
};